/*
 * Main_User.c
 *
 * Created  : 2 February 2023
 * Modified : 24 May 2023
 * Author   : HWanyusof
 * Version	: 1.2
 */

#include "usbd_cdc_if.h"
#include "string.h"
#include "stm32f4xx_hal.h"
#include "VCNL36828P.h"
#include "VCNL36828P_Prototypes.h"
#include "typedefinition.h"
#include "VCNL36828P_Application_Library.h"
#include "Main_User.h"
#include "main.h"
#include "I2C_Functions.h"

//Global Variables

/* Set the default slave address
 * VCNL36828P has 2 slave addresses depending on the Pin 5/Pin 6 (SCL/SDA) configuration.
 * Please refer to Table 1 on the datasheet
 * 1. 0x60
 * 2. 0x51
 */
int VCNL36828P_SlaveAddress = 0x60;

//Switch the I2C Bus number here (Currently only tested with Teensy3.5 with possibility to use multiple i2c channels)
// I2C_Bus = 1 for Wire 1 (Pin 18-SDA, 19-SCL)
// I2C_Bus = 2 for Wire 2 (Pin 37-SCL, 38-SDA)
//Other Arduino family boards-please use I2C_Bus = 1
//Other platforms will not be affected
int I2C_Bus = 2;

//Variables for Offset Value
int CalibValue = 0;
int AverageCount = 10; //Change the average count to the needed number of offset measurement

//Sensor Initialization
void INIT_VCNL36828P()
{
	/* Reset Sensor to default value */
	//1. Reset for sensor 1 with slave address of 0x60
	VCNL36828P_SlaveAddress = 0x60;
	Reset_Sensor();
	//2. Reset for sensor 2 with slave address of 0x60
	VCNL36828P_SlaveAddress = 0x51;
	Reset_Sensor();

	/****************************************************************************/
	/****************************Basic  Initialization***************************/
	/*
     *Basic_Initialization_Auto_Mode() uses the most basic steps to turn on the Proximity Sensor.
     *Very useful when first working with the sensor.
     *For the more advanced settings, you can use the Auto_Mode() or AF_Mode()
     */

	//1. Initialization for sensor 1 with slave address of 0x60
	VCNL36828P_SlaveAddress = 0x60;
	Basic_Initialization_Auto_Mode();

	//2. Initialization for sensor 2 with slave address of 0x51
	VCNL36828P_SlaveAddress = 0x51;
	Basic_Initialization_Auto_Mode();


	/***************************End of Initialization****************************/
    /****************************************************************************/
}

//Print Function
void PRINT_VCNL36828P()
{
	/* Print the sensor output */
	//Print Sensor 1 with slave address of 0x60
	VCNL36828P_SlaveAddress = 0x60;
	//Print_Data_Only();

	//Print Sensor 2 with slave address of 0x60
	VCNL36828P_SlaveAddress = 0x51;
	Print_Data_Only();

	HAL_Delay(500);
}

//Auto/Self-Timed Mode Basic Initialization Function
void Basic_Initialization_Auto_Mode()
{
	//1.) Initialization
	//Switch the sensor off
	VCNL36828P_SET_PS_ON(VCNL36828P_PS_ON_DIS);

	//2.) Setting up PS
	//PS_CONF1_H
	//Enable/disable high dynamic range (12 bit/16 bit) ADC output setting
	VCNL36828P_SET_PS_HD(VCNL36828P_PS_HD_16Bits);

	//PS_CONF2_L
	//Set the integration time for one measurement; the pulse length “T” is determined by PS_ITB
	VCNL36828P_SET_PS_IT(VCNL36828P_PS_IT_8T);
	//Set the pulse length “T” for PS_IT
	VCNL36828P_SET_PS_ITB(VCNL36828P_PS_ITB_50us);
	//PS_CONF2_H
	//Set the VCSEL driving current
	VCNL36828P_SET_I_VCSEL(VCNL36828P_I_VCSEL_20mA);

	//PS_CONF3_L
	//Set the measurement mode of the sensor
	VCNL36828P_SET_PS_MODE(VCNL36828P_PS_MODE_AUTO_MODE);

	//3.) Switch On the sensor
	//Enable the internal calibration
	VCNL36828P_SET_PS_CAL(VCNL36828P_PS_CAL_EN);
	//Switch the sensor on
	VCNL36828P_SET_PS_ON(VCNL36828P_PS_ON_EN);

    //Delay needs to be changed depending on the API of the µ-controller
	HAL_Delay(1000);
}


//AF/Continuous Forced Mode Initialization Function
void AF_Mode()
{
	//1.) Initialization
		//Switch the sensor off
		VCNL36828P_SET_PS_ON(VCNL36828P_PS_ON_DIS);

		//2.) Setting up PS
		//PS_CONF1_H
		//Enable/disable high dynamic range (12 bit/16 bit) ADC output setting
		VCNL36828P_SET_PS_HD(VCNL36828P_PS_HD_16Bits);
		//Enable/disable the sunlight protection mode interrupt setting
		VCNL36828P_SET_PS_SP_INT(VCNL36828P_PS_SP_INT_EN);
		//Enable/disable the smart persistence setting when the interrupt event is triggered
		VCNL36828P_SET_PS_SMART_PERS(VCNL36828P_PS_SMART_PERS_DIS);
		//Set the amount of consecutive threshold crossing events necessary to trigger interrupt
		VCNL36828P_SET_PS_PERS(VCNL36828P_PS_PERS_1);
		//Set the interrupt mode setting
		VCNL36828P_SET_PS_INT(VCNL36828P_PS_INT_LOGIC_MODE);

		//PS_CONF2_L
		//Set the measurement period
		VCNL36828P_SET_PS_PERIOD(VCNL36828P_PS_PERIOD_50ms);
		//Set the integration time for one measurement; the pulse length “T” is determined by PS_ITB
		VCNL36828P_SET_PS_IT(VCNL36828P_PS_IT_8T);
		//Set the number of infrared signal pulses per measurement
		VCNL36828P_SET_PS_MPS(VCNL36828P_PS_MPS_1);
		//Set the pulse length “T” for PS_IT
		VCNL36828P_SET_PS_ITB(VCNL36828P_PS_ITB_50us);
		//Set the gain of the ADC
		VCNL36828P_SET_PS_GAIN(VCNL36828P_PS_GAIN_x1);

		//PS_CONF2_H
		//Set the sensitivity of the ADC
		VCNL36828P_SET_PS_SENS(VCNL36828P_PS_SENS_NORMAL);
		//Enable/disable the internal crosstalk cancellation
		VCNL36828P_SET_PS_OFFSET(VCNL36828P_PS_OFFSET_EN);
		//Set the VCSEL driving current
		VCNL36828P_SET_I_VCSEL(VCNL36828P_I_VCSEL_20mA);

		//PS_CONF3_L
		//Set the measurement mode of the sensor
		VCNL36828P_SET_PS_MODE(VCNL36828P_PS_MODE_AF_MODE);

		//PS_CONF3_H
		//Set the short measurement period
		VCNL36828P_SET_PS_SHORT_PERIOD(VCNL36828P_PS_SHORT_PERIOD_DIS);
		//Enable/disable the sunlight cancellation
		VCNL36828P_SET_PS_SC(VCNL36828P_PS_SC_EN);

		//3.) Switch On the sensor
		//Enable the internal calibration
		VCNL36828P_SET_PS_CAL(VCNL36828P_PS_CAL_EN);
		//Switch the sensor on
		VCNL36828P_SET_PS_ON(VCNL36828P_PS_ON_EN);

		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);

		//Clear Initial Interrupt
		VCNL36828P_GET_INT_FLAG();
		HAL_Delay(10);

		//4.) Threshold Setting and Offset Measurement
		for(int i=0;i<AverageCount;i++)
		{
			//Set trigger to start a measurement
		    VCNL36828P_SET_PS_TRIG(VCNL36828P_PS_TRIG_EN);
			//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
			HAL_Delay(10);
			CalibValue += VCNL36828P_GET_PS_DATA();
			//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
			HAL_Delay(10);
		}

		//Calculate the average of the offset measurement
		CalibValue /= AverageCount;

		//Set the offset count cancellation value
		VCNL36828P_SET_PS_CANC(CalibValue);
		//Set the low threshold interrupt value
		VCNL36828P_SET_PS_THDL(3000);
		//Set the high threshold interrupt value
		VCNL36828P_SET_PS_THDH(4000);

		HAL_Delay(1000);
}

//Auto/Self-Timed Mode Initialization Function
void Auto_Mode()
{
	//1.) Initialization
	//Switch the sensor off
	VCNL36828P_SET_PS_ON(VCNL36828P_PS_ON_DIS);

	//2.) Setting up PS
	//PS_CONF1_H
	//Enable/disable high dynamic range (12 bit/16 bit) ADC output setting
	VCNL36828P_SET_PS_HD(VCNL36828P_PS_HD_16Bits);
	//Enable/disable the sunlight protection mode interrupt setting
	VCNL36828P_SET_PS_SP_INT(VCNL36828P_PS_SP_INT_EN);
	//Enable/disable the smart persistence setting when the interrupt event is triggered
	VCNL36828P_SET_PS_SMART_PERS(VCNL36828P_PS_SMART_PERS_DIS);
	//Set the amount of consecutive threshold crossing events necessary to trigger interrupt
	VCNL36828P_SET_PS_PERS(VCNL36828P_PS_PERS_1);
	//Set the interrupt mode setting
	VCNL36828P_SET_PS_INT(VCNL36828P_PS_INT_LOGIC_MODE);

	//PS_CONF2_L
	//Set the measurement period
	VCNL36828P_SET_PS_PERIOD(VCNL36828P_PS_PERIOD_50ms);
	//Set the integration time for one measurement; the pulse length “T” is determined by PS_ITB
	VCNL36828P_SET_PS_IT(VCNL36828P_PS_IT_8T);
	//Set the number of infrared signal pulses per measurement
	VCNL36828P_SET_PS_MPS(VCNL36828P_PS_MPS_1);
	//Set the pulse length “T” for PS_IT
	VCNL36828P_SET_PS_ITB(VCNL36828P_PS_ITB_50us);
	//Set the gain of the ADC
	VCNL36828P_SET_PS_GAIN(VCNL36828P_PS_GAIN_x1);

	//PS_CONF2_H
	//Set the sensitivity of the ADC
	VCNL36828P_SET_PS_SENS(VCNL36828P_PS_SENS_NORMAL);
	//Enable/disable the internal crosstalk cancellation
	VCNL36828P_SET_PS_OFFSET(VCNL36828P_PS_OFFSET_EN);
	//Set the VCSEL driving current
	VCNL36828P_SET_I_VCSEL(VCNL36828P_I_VCSEL_20mA);

	//PS_CONF3_L
	//Set the measurement mode of the sensor
	VCNL36828P_SET_PS_MODE(VCNL36828P_PS_MODE_AUTO_MODE);

	//PS_CONF3_H
	//Set the short measurement period
	VCNL36828P_SET_PS_SHORT_PERIOD(VCNL36828P_PS_SHORT_PERIOD_DIS);
	//Enable/disable the sunlight cancellation
	VCNL36828P_SET_PS_SC(VCNL36828P_PS_SC_EN);

	//3.) Switch On the sensor
	//Enable the internal calibration
	VCNL36828P_SET_PS_CAL(VCNL36828P_PS_CAL_EN);
	//Switch the sensor on
	VCNL36828P_SET_PS_ON(VCNL36828P_PS_ON_EN);

	//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
	HAL_Delay(10);

	//Clear Initial Interrupt
	VCNL36828P_GET_INT_FLAG();
	HAL_Delay(10);

	//4.) Threshold Setting and Offset Measurement
	for(int i=0;i<AverageCount;i++)
	{
		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);
		CalibValue += VCNL36828P_GET_PS_DATA();
		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);
	}

	//Calculate the average of the offset measurement
	CalibValue /= AverageCount;

	//Set the offset count cancellation value
	VCNL36828P_SET_PS_CANC(CalibValue);
	//Set the low threshold interrupt value
	VCNL36828P_SET_PS_THDL(3000);
	//Set the high threshold interrupt value
	VCNL36828P_SET_PS_THDH(4000);

	HAL_Delay(1000);
}
